package com.gmq.mianshi.designModel.singleton;

/**
 * 懒汉式单例类
 *
 * @author gmq
 * @email 2628931@qq.com
 * @date 2017/11/22 22:13
 */
public class Singleton01 {

    private static Singleton01 singleton = null;

    private Singleton01() {

    }

    //静态工厂方法(线程不安全的)
//    public static Singleton01 getInstance() {
//        if (singleton == null) {
//            singleton = new Singleton01();
//        }
//
//        return singleton;
//    }

    /*Singleton通过将构造方法限定为private避免了类在外部被实例化，在同一个虚拟机范围内，Singleton的唯一实例只能通过getInstance()方法访问。
            （事实上，通过Java反射机制是能够实例化构造方法为private的类的，那基本上会使所有的Java单例实现失效。此问题在此处不做讨论，姑且掩耳盗铃地认为反射机制不存在。）
    但是以上懒汉式单例的实现没有考虑线程安全问题，它是线程不安全的，并发环境下很可能出现多个Singleton实例，
    */
    // 要实现线程安全，有以下三种方式，都是对getInstance这个方法改造，保证了懒汉式单例的线程安全，如果你第一次接触单例模式，
    // 对线程安全不是很了解，可以先跳过下面这三小条，去看饿汉式单例，等看完后面再回头考虑线程安全的问题：
    // 1、在getInstance方法上加同步(性能比较差)
//    public static synchronized Singleton01 getInstance() {
//        if (singleton == null) {
//            singleton = new Singleton01();
//        }
//
//        return singleton;
//    }

    // 2、双重检查锁定
//    public static synchronized Singleton01 getInstance() {
//        if (singleton == null) {
//            synchronized (Singleton01.class) {
//                if (singleton == null) {
//                    singleton = new Singleton01();
//                }
//            }
//        }
//
//        return singleton;
//    }

    // 3、静态内部类: 这种比上面1、2都好一些，既实现了线程安全，又避免了同步带来的性能影响。
    private static class LazyHolder {
        private static final Singleton01 INSTANCE = new Singleton01();
    }

    public static final Singleton01 getInstance() {
        return LazyHolder.INSTANCE;
    }
}
